package com.bysc.cmsservice.caller;

import cn.hutool.json.JSONUtil;
import com.bysc.baseservice.handler.BaiYunException;
import com.bysc.cmsservice.entity.dto.AiDto;
import com.bysc.cmsservice.entity.vo.CmsAiVo;
import com.bysc.cmsservice.factory.SystemContentStrategyFactory;
import com.bysc.cmsservice.service.CmsActivityService;
import com.bysc.cmsservice.strategy.SystemContentStrategy;
import com.bysc.commonutils.ResultCode;
import com.google.gson.*;
import okhttp3.*;
import org.apache.http.HttpHeaders;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class KimiAiCaller implements AiCaller {
    @Resource
    private CmsActivityService cmsActivityService;
    private static final String API_KEY = "sk-b8Qti6WgFSwvhoksNiB66l3yGqgEhIKvPmeQI1UWpvOQFFYy";
    private static final String BASE_URL = "https://api.moonshot.cn/v1/chat/completions";
    private static final Gson GSON = new Gson();

    private static final OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.MINUTES)
            .writeTimeout(10, TimeUnit.MINUTES)
            .readTimeout(10, TimeUnit.MINUTES)
            .build();

    private List<Map<String, String>> history = new ArrayList<>();

    @Override
    public void init() {
        // 初始化逻辑（如果需要）
    }

    @Override
    public void getReply(AiDto aiDto, HttpServletRequest userRequest, HttpServletResponse response) throws Exception {
        MediaType mediaType = MediaType.parse("application/json");
        response.setHeader(HttpHeaders.CONTENT_TYPE, mediaType.toString());
        response.setCharacterEncoding("UTF-8");
        response.setHeader(HttpHeaders.PRAGMA, "no-cache");
        ServletOutputStream out = null;
        String[] messages = aiDto.getMessages();
        String scene = aiDto.getScene();

        JsonObject requestBody = new JsonObject();
        requestBody.addProperty("model", "moonshot-v1-8k");
        requestBody.addProperty("temperature", 0.3);
        requestBody.addProperty("stream", true);

        JsonArray messagesArray = new JsonArray();
        // 动态更改system消息
        JsonObject systemObj = new JsonObject();
        systemObj.addProperty("role", "system");
        SystemContentStrategy strategy = SystemContentStrategyFactory.createStrategy(scene);
        systemObj.addProperty("content", strategy.getSystemContent());
        messagesArray.add(systemObj); // 将system消息添加到最前面
        // 处理入参messages
        for (int i = 0; i < messages.length; i++) {
            JsonObject messageObj = new JsonObject();
            messageObj.addProperty("role", i % 2 == 0 ? "user" : "assistant");
            messageObj.addProperty("content", messages[i]);
            messagesArray.add(messageObj);
        }
        requestBody.add("messages", messagesArray);
        String requestBodyStr = GSON.toJson(requestBody);

        RequestBody body = RequestBody.create(requestBodyStr, MediaType.get("application/json; charset=utf-8"));

        Request request = new Request.Builder()
                .url(BASE_URL)
                .post(body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Authorization", "Bearer " + API_KEY)
                .build();

        out = response.getOutputStream();

        try (Response resp = client.newCall(request).execute()) {
            if (!resp.isSuccessful()) {
                throw new IOException("Unexpected code " + resp);
            }

            // 获取响应体的输入流
            InputStream inputStream = resp.body().byteStream();

            // 逐行读取响应内容
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            String line;
            while ((line = reader.readLine()) != null) {
                // 去掉前缀 "data: " 和后缀 "\n\n"
                if(line.endsWith("[DONE]")) {
                    return;
                }
                if (line.startsWith("data: ")) {
                    line = line.substring(6); // 去掉 "data: "
                    try {
                        JsonObject jsonObject = GSON.fromJson(line, JsonObject.class);
                        JsonObject choice = jsonObject.getAsJsonArray("choices").get(0).getAsJsonObject();
                        JsonObject delta = choice.getAsJsonObject("delta");
                        String content = delta.has("content") ? delta.get("content").getAsString() : "";
                        JsonElement finish_reason = choice.get("finish_reason");
                        Boolean isEnd = false;
                        if (finish_reason != null && ! (finish_reason instanceof JsonNull)) {
                            isEnd = finish_reason.getAsString().equals("stop");
                        }
                        //TODO scene字符串统一管理
                        if ("activityCreator".equals(scene)) {
                            if (content.contains("感谢")) {
                                // 解析并插入活动信息
                                cmsActivityService.parseAndInsertActivity(messages[messages.length - 2], userRequest);
                            }
                        }
                        // 构建返回对象
                        CmsAiVo cmsAiVo = new CmsAiVo(content, isEnd);
                        System.out.println(cmsAiVo);
                        // 将提取的内容逐步返回给前端
                        out.write(JSONUtil.toJsonStr(cmsAiVo).getBytes("UTF-8"));
                        out.flush();
                    } catch (Exception e) {
                        throw new BaiYunException(ResultCode.ERROR, "解析响应内容失败: " + e.getMessage());
                    }
                }

            }
            // 关闭资源
            reader.close();
            inputStream.close();
        } catch (BaiYunException e) {
            e.printStackTrace();
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("系统内部错误，请联系管理员", e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
                throw new BaiYunException(ResultCode.ERROR, "关闭输出流失败");
            }
        }
    }
}